/*
 * c05_integer_conversion - 整数类型转换：as关键字的使用
 * 
 * 本程序演示Rust中整数类型之间的转换方法：
 * 1. 使用as关键字进行类型转换
 * 2. 不同位宽之间的转换
 * 3. 有符号和无符号整数的转换
 * 4. 处理转换中的溢出和截断问题
 * 5. 类型转换的安全性考虑
 */

fn main() {
    println!("=== Rust 整数类型转换示例 ===\n");
    
    // 1. 基础类型转换 - 从小位宽到大位宽（安全转换）
    basic_conversions();
    
    // 2. 从大位宽到小位宽的转换（可能发生截断）
    truncation_examples();
    
    // 3. 有符号和无符号整数之间的转换
    signed_unsigned_conversions();
    
    // 4. 转换中的溢出处理
    overflow_handling();
    
    // 5. 实际应用场景
    practical_examples();
    
    // 6. 类型转换的最佳实践
    best_practices();
}

/// 基础类型转换示例 - 从小位宽到大位宽
fn basic_conversions() {
    println!("1. 基础类型转换（小 -> 大位宽）");
    println!("   这种转换是安全的，不会丢失精度\n");
    
    // i8 -> i16 -> i32 -> i64
    let small_int: i8 = 42;
    println!("原始值: {} (i8类型)", small_int);
    
    let medium_int = small_int as i16;
    println!("转换为i16: {}", medium_int);
    
    let large_int = medium_int as i32;
    println!("转换为i32: {}", large_int);
    
    let extra_large_int = large_int as i64;
    println!("转换为i64: {}", extra_large_int);
    
    // 无符号整数的向上转换
    let small_uint: u8 = 255;
    println!("\n原始值: {} (u8类型)", small_uint);
    
    let large_uint = small_uint as u32;
    println!("转换为u32: {}", large_uint);
    
    println!("   ✓ 向上转换是安全的，值保持不变\n");
    println!("{}", "=".repeat(50));
}

/// 展示从大位宽到小位宽的转换（截断）
fn truncation_examples() {
    println!("2. 大位宽到小位宽的转换（截断示例）");
    println!("   这种转换可能会丢失数据，需要特别小心\n");
    
    // 64位整数转换为32位
    let big_number: i64 = 2147483647;  // i32的最大值
    let truncated = big_number as i32;
    println!("i64: {} -> i32: {} ✓ 在范围内", big_number, truncated);
    
    // 超出范围的转换
    let too_big: i64 = 2147483648;  // 超出i32最大值
    let truncated_overflow = too_big as i32;
    println!("i64: {} -> i32: {} ⚠️ 发生溢出", too_big, truncated_overflow);
    
    // u32转换为u8的例子
    let large_uint: u32 = 300;
    let small_uint = large_uint as u8;
    println!("u32: {} -> u8: {} (截断：300 % 256 = 44)", large_uint, small_uint);
    
    // 展示二进制表示帮助理解截断
    println!("\n截断原理解释：");
    println!("300的二进制: {:016b}", 300u16);
    println!("只保留低8位: {:08b} = {}", 44u8, 44u8);
    
    println!("   ⚠️ 大转小可能会丢失高位数据\n");
    println!("{}", "=".repeat(50));
}

/// 有符号和无符号整数之间的转换
fn signed_unsigned_conversions() {
    println!("3. 有符号与无符号整数转换");
    println!("   需要理解二进制补码表示法\n");
    
    // 正数的转换
    let positive: i32 = 100;
    let as_unsigned = positive as u32;
    println!("正数转换:");
    println!("i32: {} -> u32: {} ✓ 正数转换安全", positive, as_unsigned);
    
    // 负数转换为无符号数
    let negative: i32 = -100;
    let negative_as_unsigned = negative as u32;
    println!("\n负数转换:");
    println!("i32: {} -> u32: {}", negative, negative_as_unsigned);
    println!("说明: 负数的二进制表示被重新解释为无符号数");
    
    // 展示二进制表示
    println!("二进制表示:");
    println!("-100 (i32): {:032b}", -100i32);
    println!("结果 (u32): {:032b} = {}", negative_as_unsigned, negative_as_unsigned);
    
    // 大的无符号数转换为有符号数
    let large_unsigned: u32 = 3000000000;  // 大于i32最大值
    let as_signed = large_unsigned as i32;
    println!("\n大无符号数转有符号数:");
    println!("u32: {} -> i32: {}", large_unsigned, as_signed);
    println!("说明: 超出i32范围的u32会被解释为负数");
    
    println!("   ⚠️ 有符号/无符号转换需要理解内存表示\n");
    println!("{}", "=".repeat(50));
}

/// 转换中的溢出处理
fn overflow_handling() {
    println!("4. 转换溢出的处理与检测");
    println!("   了解不同的溢出处理策略\n");
    
    // 演示不同大小的数值转换
    let values = [100i32, 256, 65536, -1, -256];
    
    for &value in &values {
        println!("原始值 (i32): {}", value);
        
        // 转换为u8
        let as_u8 = value as u8;
        println!("  -> u8: {} ({})", as_u8, 
                if value >= 0 && value <= 255 { "正常" } 
                else { "发生截断/溢出" });
        
        // 转换为i16
        let as_i16 = value as i16;
        println!("  -> i16: {} ({})", as_i16,
                if value >= i16::MIN as i32 && value <= i16::MAX as i32 { "正常" }
                else { "发生溢出" });
        
        println!();
    }
    
    // 展示使用try_into进行安全转换的概念
    println!("💡 安全转换提示：");
    println!("   虽然as关键字总是会成功，但可能丢失数据");
    println!("   对于安全要求高的场景，考虑使用bounds检查");
    
    println!("   ⚠️ as转换不会panic，但可能产生意外结果\n");
    println!("{}", "=".repeat(50));
}

/// 实际应用场景
fn practical_examples() {
    println!("5. 实际应用场景");
    println!("   类型转换在实际开发中的常见用途\n");
    
    // 场景1：数组索引
    println!("场景1: 数组索引转换");
    let data = [10, 20, 30, 40, 50];
    let index_as_u8: u8 = 2;
    let index = index_as_u8 as usize;  // 数组索引必须是usize类型
    println!("使用u8索引 {} 访问数组: data[{}] = {}", index_as_u8, index, data[index]);
    
    // 场景2：网络协议中的类型转换
    println!("\n场景2: 网络字节序转换");
    let port: u16 = 8080;
    let port_high_byte = (port >> 8) as u8;
    let port_low_byte = port as u8;
    println!("端口号 {} 分解为字节:", port);
    println!("  高字节: {}, 低字节: {}", port_high_byte, port_low_byte);
    
    // 重新组装
    let reconstructed = ((port_high_byte as u16) << 8) | (port_low_byte as u16);
    println!("  重新组装: {}", reconstructed);
    
    // 场景3：处理用户输入
    println!("\n场景3: 用户输入范围限制");
    let user_input = 1000i32;  // 假设这是用户输入
    let max_u8 = u8::MAX as i32;
    
    if user_input >= 0 && user_input <= max_u8 {
        let safe_value = user_input as u8;
        println!("用户输入 {} 转换为u8: {}", user_input, safe_value);
    } else {
        println!("用户输入 {} 超出u8范围 (0-{})", user_input, max_u8);
    }
    
    // 场景4：计算中的类型提升
    println!("\n场景4: 避免计算溢出");
    let a: u8 = 200;
    let b: u8 = 100;
    
    // 直接计算可能溢出
    println!("u8计算: {} + {} = {}", a, b, a.wrapping_add(b));
    
    // 提升到更大类型进行计算
    let result = (a as u16) + (b as u16);
    println!("提升到u16计算: {} + {} = {}", a, b, result);
    
    if result <= u8::MAX as u16 {
        println!("结果 {} 可以安全转换回u8: {}", result, result as u8);
    } else {
        println!("结果 {} 超出u8范围", result);
    }
    
    println!("   ✓ 实际应用中要根据场景选择合适的转换策略\n");
    println!("{}", "=".repeat(50));
}

/// 类型转换的最佳实践
fn best_practices() {
    println!("6. 类型转换最佳实践");
    println!("   安全、清晰、可维护的转换代码\n");
    
    println!("💡 最佳实践建议:");
    println!();
    
    println!("1. 明确转换意图");
    println!("   ✓ 向上转换（扩展位宽）：通常安全");
    println!("   ⚠️ 向下转换（缩小位宽）：需要验证范围");
    println!("   ⚠️ 符号转换：需要理解二进制表示");
    
    println!("\n2. 添加合适的注释和检查");
    let value: i64 = 42;
    // 安全的向上转换，无需检查
    let expanded = value as i128;
    println!("   // 安全转换：{} -> {}", value, expanded);
    
    let big_value: i64 = 300;
    // 向下转换前检查范围
    if big_value >= i8::MIN as i64 && big_value <= i8::MAX as i64 {
        let checked_conversion = big_value as i8;
        println!("   // 范围检查通过：{} -> {}", big_value, checked_conversion);
    } else {
        println!("   // 范围检查失败：{} 超出i8范围", big_value);
    }
    
    println!("\n3. 考虑使用常量和范围检查");
    const MAX_VALID_U8: i32 = 255;
    const MIN_VALID_U8: i32 = 0;
    
    let input = 200i32;
    if input >= MIN_VALID_U8 && input <= MAX_VALID_U8 {
        let safe_u8 = input as u8;
        println!("   // 使用常量检查：{} -> u8: {}", input, safe_u8);
    }
    
    println!("\n4. 在关键场景中记录转换逻辑");
    println!("   // 网络字节序转换");
    println!("   // 用户输入验证");
    println!("   // 数学计算精度控制");
    
    println!("\n总结：");
    println!("• as关键字是Rust中最基础的类型转换方式");
    println!("• 转换总是会成功，但可能改变数值");
    println!("• 向上转换安全，向下转换需要小心");
    println!("• 在生产代码中添加适当的检查和注释");
    println!("• 理解二进制表示有助于预测转换结果");
    
    println!("\n🎉 学习完成！你现在掌握了Rust整数类型转换的核心概念！");
}
